package org.hit.burkun.umls.relation.merge;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.hit.burkun.db.DBHelper;
import org.hit.burkun.db.DBTypeConverter;
import org.hit.burkun.db.DBTypeConverter.DATATYPE;
import org.hit.burkun.dbimport.MemoryImport;
import org.hit.burkun.entities.Entity;
import org.hit.burkun.entities.Entity.TYPE;
import org.hit.burkun.umls.GeneralQuery;
import org.hit.burkun.umls.relation.UniformRelation;

public class StaticMethods {
	public static HashMap<String, LinkedList<GeneMergeObject>> merge(
			HashMap<String, LinkedList<GeneMergeObject>> org,
			HashMap<String, LinkedList<GeneMergeObject>> dst) {
		Set<Entry<String, LinkedList<GeneMergeObject>>> set = org.entrySet();
		for (Entry<String, LinkedList<GeneMergeObject>> en : set) {
			String key = en.getKey();
			if (dst.containsKey(key)) {
				LinkedList<GeneMergeObject> oldLs = en.getValue();
				LinkedList<GeneMergeObject> ls = dst.get(key);
				LinkedList<GeneMergeObject> newLs = new LinkedList<>();
				for (GeneMergeObject go : oldLs) {
					boolean isFind = false;
					for (GeneMergeObject lsGo : ls) {
						if (go.geneid.equals(lsGo.geneid)) {
							lsGo.evideces.append("," + go.evideces.toString());
							lsGo.score.append("," + go.score.toString());
							isFind = true;
							break;
						}
					}
					if (!isFind) {
						// 加上老的
						newLs.add(go);
					}
				}
				newLs.addAll(ls);
				// renew
				dst.put(key, newLs);
			} else {
				dst.put(key, en.getValue());
			}
		}
		return dst;
	}

	// hp - umls
	public static HashMap<String, HashSet<String>> getEntityUmls(
			Entity.TYPE type) {
		return GeneralQuery.getEntityUmlsMap(type);
	}

	// ent1_dbid,ent1_umls,ent2_dbid,rel_detial
	public static HashMap<String, LinkedList<GeneMergeObject>> getEntity2Entity(
			UniformRelation.TYPE type) {
		DBHelper dbh = DBHelper.getLocalBioData();
		dbh.connectionDB();
		Collection<String[]> res = dbh
				.queryData(
						"SELECT ent1_dbid ,ent2_dbid,rel_detials,scores FROM birelation where rel_detials = '"
								+ type.getTag() + "'", 4);
		dbh.disconnection();
		HashMap<String, LinkedList<GeneMergeObject>> doumls = new HashMap<String, LinkedList<GeneMergeObject>>();
		for (String[] line : res) {
			if (doumls.containsKey(line[0])) {
				GeneMergeObject go = new GeneMergeObject();
				go.geneid = line[1];
				go.evideces.append(line[2]);
				go.score.append(line[3]);
				doumls.get(line[0]).add(go);
			} else {
				LinkedList<GeneMergeObject> set = new LinkedList<>();
				GeneMergeObject go = new GeneMergeObject();
				go.geneid = line[1];
				go.evideces.append(line[2]);
				go.score.append(line[3]);
				set.add(go);
				doumls.put(line[0], set);
			}
		}
		return doumls;
	}

	public static HashMap<String, LinkedList<GeneMergeObject>> getEntityUmls2EntityDbid(
			UniformRelation.TYPE type) {
		DBHelper dbh = DBHelper.getLocalBioData();
		dbh.connectionDB();
		Collection<String[]> res = dbh
				.queryData(
						"SELECT ent1_umls ,ent2_dbid,rel_detials,scores FROM birelation where rel_detials = '"
								+ type.getTag() + "'", 4);
		dbh.disconnection();
		HashMap<String, LinkedList<GeneMergeObject>> doumls = new HashMap<String, LinkedList<GeneMergeObject>>();
		for (String[] line : res) {
			if (doumls.containsKey(line[0])) {
				GeneMergeObject go = new GeneMergeObject();
				go.geneid = line[1];
				go.evideces.append(line[2]);
				go.score.append(line[3]);
				doumls.get(line[0]).add(go);
			} else {
				LinkedList<GeneMergeObject> set = new LinkedList<>();
				GeneMergeObject go = new GeneMergeObject();
				go.geneid = line[1];
				go.evideces.append(line[2]);
				go.score.append(line[3]);
				set.add(go);
				doumls.put(line[0], set);
			}
		}
		return doumls;
	}
	
	// 通过umlsid，整合clinvar的数据，其中，只要clinvar中有一个umls 出现在某个hp节点上，就将这个gene给这个hp节点
	public static HashMap<String, LinkedList<GeneMergeObject>> mergeFromEntityByUmls(
			Entity.TYPE type, UniformRelation.TYPE relType) {
		// 获取clinvar的数据。。。。,umls id 到 gene
		HashMap<String, LinkedList<GeneMergeObject>> clinvar = getEntityUmls2EntityDbid(relType);
		HashMap<String, HashSet<String>> doUmls = getEntityUmls(type);
		HashMap<String, LinkedList<GeneMergeObject>> map = new HashMap<>();
		Set<String> keys = doUmls.keySet();
		for (String doid : keys) {
			if (doid != null) {
				Set<String> umls = doUmls.get(doid);
				Set<Entry<String, LinkedList<GeneMergeObject>>> set = clinvar
						.entrySet();
				for (Entry<String, LinkedList<GeneMergeObject>> en : set) {
					if (umls.contains(en.getKey())) {
						map.put(doid, en.getValue());
					}
				}
			}
		}
		return map;
	}

	public static Collection<String[]> formatToEntity2GeneDbRelWithoutPrimaryId(
			HashMap<String, LinkedList<GeneMergeObject>> data, TYPE type1) {
		HashMap<String, HashSet<String>> typeUmls1 = getEntityUmls(type1);
		HashMap<String, HashSet<String>> typeUmls2 = getEntityUmls(TYPE.GENE_ID);
		LinkedList<String[]> res = new LinkedList<>();
		// dbid, geneid, with evidence and score
		Set<Entry<String, LinkedList<GeneMergeObject>>> set = data.entrySet();
		for (Entry<String, LinkedList<GeneMergeObject>> en : set) {
			String en1 = en.getKey();
			LinkedList<GeneMergeObject> ls = en.getValue();
			if (typeUmls1.containsKey(en1)) {
				for (GeneMergeObject go : ls) {
					if (typeUmls2.containsKey(go.geneid)) {
						Set<String> umls1 = typeUmls1.get(en1);
						Set<String> umls2 = typeUmls2.get(go.geneid);
						String u1 = StringUtils.join(umls1, ",");
						String u2 = StringUtils.join(umls2, ",");
						String[] line = new String[8];
						line[0] = type1.getTag();
						line[1] = en1;
						line[2] = u1;
						line[3] = TYPE.GENE_ID.getTag();
						line[4] = go.geneid;
						line[5] = u2;
						line[6] = go.evideces.toString();
						line[7] = calcCombineScores(line[6], go.score.toString());
						res.add(line);
					}
				}
			}
		}
		return res;
	}
	
	private static String calcCombineScores(String evideces, String scores){
		String[] es = evideces.split(",");
		String[] ss = scores.split(",");
		if(es.length != ss.length){
			System.out.println("error, evidece length != scores length");
			System.exit(-1);
		}
		HashSet<String> maker = new HashSet<>();
		//remove same evidence, 只适用于一个的情况。
		boolean[] sameMaker =new  boolean[es.length];
		boolean isMarked = false;
		for(int i=0; i<es.length; i++){
			org.hit.burkun.umls.relation.UniformRelation.TYPE type = UniformRelation.TYPE.getTypeByTag(es[i]);
			if(UniformRelation.containSame(type)){
				if(isMarked){
					sameMaker[i] = true;//不计入
				}else{
					//保证第一个是false
					isMarked = true;
				}
			}
		}
		double combineScore = 1.0;
		for(int i=0; i<ss.length ; i++){
			//不包含且没被标记
			if(!maker.contains(es[i]) && !sameMaker[i]){
				if(!ss[i].equals("null")){
					double v = Double.parseDouble(ss[i]);
					combineScore *= (1-v);
				}else{
					double v = UniformRelation.getScoreByType(es[i]);
					combineScore *= (1-v);
				}
				maker.add(es[i]);
			}
		}
		return String.valueOf(1-combineScore);
	}
	

	// 不带自增的
	public static void dumpRelationsWithoutPrimaryId(
			Collection<String[]> baseRel, String tbName) {
		DATATYPE[] types = new DATATYPE[8];
		// types[7] = DATATYPE.D;
		DBTypeConverter typeConverter = new DBTypeConverter(types);
		MemoryImport imp = new MemoryImport(tbName, DBHelper.getLocalBioData(),
				false, typeConverter);
		imp.doImport(baseRel, fileds);
	}

	private static String[] fileds = new String[] { "ent1_type", "ent1_dbid",
			"ent1_umls", "ent2_type", "ent2_dbid", "ent2_umls", "rel_detials",
			"scores" };

}
